# 增加应用程序和第三方库 ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # 概述 本文档指导用户在Yocto构建系统中添加自定义应用程序和第三方库(以helloworld为例)。通过本文档的步骤,您可以: - 将自定义代码集成到Yocto项目中 - 生成IPK安装包 - 编译和使用第三方库文件 - 将组件集成到系统镜像中 # 前置准备 ## 环境要求 - 已安装必要的开发工具包 - 已克隆Yocto项目代码 - 熟悉基本的C语言编程 - 了解Makefile和BitBake基础 ## 项目目录结构 创建自定义meta层,推荐使用以下目录结构: ```plaintext meta-custom/ ├── conf/ │ └── layer.conf # 层配置文件 ├── recipes-apps/ # 应用程序配方目录 │ └── helloworld/ │ ├── files/ │ │ ├── helloworld.c # 应用源码 │ │ ├── Makefile # 编译脚本 │ │ └── helloworld.service # systemd服务文件 │ └── helloworld_1.0.bb # BitBake配方 └── recipes-libs/ # 库配方目录 └── lib-helloworld/ ├── files/ │ ├── lib_helloworld.c # 库源码 │ ├── lib_helloworld.h # 库头文件 │ └── Makefile # 编译脚本 └── lib-helloworld_1.0.bb # BitBake配方 ``` # 添加自定义应用程序 ## 创建层目录结构 ### 创建目录 ```bash mkdir -p ${YOCTO_DIR}/layers/meta-custom/recipes-apps/helloworld/files mkdir -p ${YOCTO_DIR}/layers/meta-custom/conf ``` ### 配置自定义层 在 *layers/meta-custom/conf/layer.conf* 文件中添加: ```plaintext BBPATH .= ":${LAYERDIR}" BBFILES += "${LAYERDIR}/recipes-*/*/*.bb" LAYERDEPENDS_meta-custom = "core" LAYERSERIES_COMPAT_meta-custom = "kirkstone" ``` ### 注册层到构建系统 编辑 *layers/meta-qcom-distro/conf/bblayers.conf*,添加自定义层路径: ```plaintext BBLAYERS = " \ ${WORKSPACE}/layers/meta-custom \ " ``` ### 添加到镜像配方 编辑 *layers/meta-quectel/recipes-products/images/qcom-multimedia-image.bbappend*,添加: ```plaintext # 添加应用程序 IMAGE_INSTALL:append = " helloworld" # 添加库文件(如果需要) IMAGE_INSTALL:append = " \ lib-helloworld \ lib-helloworld-dev \ lib-helloworld-staticdev \ " ``` ## 创建应用程序源码 ### 编写主程序 在 *meta-custom/recipes-apps/helloworld/files/* 目录下创建 *helloworld.c*: ```c // helloworld.c#include int main() {printf("Hello, world!\n");return 0;} ``` ### 编写Makefile 在 *meta-custom/recipes-apps/helloworld/files/* 目录下创建 *Makefile*: ```makefile # 使用Yocto提供的编译标志all: helloworld helloworld: helloworld.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $) [镜像烧录](<../镜像烧录/镜像烧录.md>) **步骤5:验证安装** 烧录完成后,在设备上执行: ```bash /usr/bin/helloworld ``` 预期输出: ```plaintext Hello, world! ``` # 添加第三方库 ## 创建库文件 ### 创建目录 ```bash mkdir -p ${YOCTO_DIR}/layers/meta-custom/recipes-libs/lib-helloworld/files ``` ### 创建库头文件 在 *meta-custom/recipes-libs/lib-helloworld/files/* 目录下创建 *lib_helloworld.h*: ```c // lib_helloworld.h#ifndef LIB_HELLO_H#define LIB_HELLO_Hvoid hello_print(const char* name);#endif ``` ### 创建库源码 在 *meta-custom/recipes-libs/lib-helloworld/files/* 目录下创建 *lib_helloworld.c*: ```c // lib_helloworld.c#include #include "lib_helloworld.h"void hello_print(const char* name) {printf("[LIB] Hello, %s!\n", name);} ``` ### 编写Makefile 在 *meta-custom/recipes-libs/lib-helloworld/files/* 目录下创建 *Makefile*: ```makefile LIB_VERSION = 1.0 all:${CC} ${CFLAGS} -fPIC -c lib_helloworld.c -o lib_helloworld.o ${CC} ${CFLAGS} -fPIC -shared lib_helloworld.o -o libhello.so.${LIB_VERSION} \ -Wl,-soname,libhello.so.1 ${LDFLAGS} ar rcs libhello.a lib_helloworld.o ln -sf libhello.so.${LIB_VERSION} libhello.so ln -sf libhello.so.${LIB_VERSION} libhello.so.1 clean: rm -f libhello.so* lib_helloworld.o libhello.a ``` ## 编写BitBake配方 在 *meta-custom/recipes-libs/lib-helloworld/* 目录下创建 *lib-helloworld_1.0.bb*: ```python SUMMARY = "Hello World Library" SECTION = "libs" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI = "file://lib_helloworld.c \ file://lib_helloworld.h \ file://Makefile" S = "${WORKDIR}" EXTRA_OEMAKE = "'CC=${CC}' 'CFLAGS=${CFLAGS} -fPIC' 'LDFLAGS=${LDFLAGS}'" do_install() {# 创建目标目录 install -d ${D}${libdir} install -d ${D}${includedir}# 安装共享库及符号链接 install -m 0755 ${S}/libhello.so.${PV} ${D}${libdir}/ ln -sf libhello.so.${PV} ${D}${libdir}/libhello.so ln -sf libhello.so.${PV} ${D}${libdir}/libhello.so.1# 安装静态库 install -m 0644 ${S}/libhello.a ${D}${libdir}/# 安装头文件 install -m 0644 ${S}/lib_helloworld.h ${D}${includedir}/}# 包文件分配 FILES:${PN} = " \ ${libdir}/libhello.so.1 \ ${libdir}/libhello.so.${PV} \ " FILES:${PN}-dev = " \ ${libdir}/libhello.so \ ${includedir}/lib_helloworld.h \ " FILES:${PN}-staticdev = " \ ${libdir}/libhello.a \ " ``` ## 构建和使用第三方库 ### 配置构建环境 ```bash source quectel_build/compile/build.sh ``` ### 方式一:单独编译并安装 **步骤1:编译库** ```bash bitbake lib-helloworld ``` **步骤2:查找生成的库文件** ```bash find ./* -name "libhello*" ``` **步骤3:推送到设备** ```bash adb push libhello.so libhello.so.1 libhello.so.1.0 libhello.a /usr/lib ``` **步骤4:修复权限和符号链接** 在设备上执行: ```bash # 设置执行权限chmod 755 /usr/lib/libhello.so* chmod 644 /usr/lib/libhello.a # 重建符号链接cd /usr/lib ln -sf libhello.so.1.0 libhello.so.1 ln -sf libhello.so.1 libhello.so ``` **步骤5:编写测试程序** 创建静态库测试程序 *static_test_helloworld.c*: ```c #include void hello_print(const char*);int main() {printf("static lib test\n");hello_print("world");return 0;} ``` 创建动态库测试程序 *dynamic_test_helloworld.c*: ```c #include void hello_print(const char*);int main() {printf("dynamic lib test\n");hello_print("world");return 0;} ``` **步骤6:编译并运行测试程序** 静态库测试: ```bash gcc static_test_helloworld.c -lhello -static -o static_hello ./static_hello ``` 预期输出: ```plaintext static lib test [LIB] Hello, world! ``` 动态库测试: ```bash gcc dynamic_test_helloworld.c /usr/lib/libhello.so -o dynamic_hello ./dynamic_hello ``` 预期输出: ```plaintext dynamic lib test [LIB] Hello, world! ``` ### 方式二:整编系统镜像 **编译和烧录** 参考前面"添加自定义应用程序"章节中"方式二:整编系统镜像"的步骤进行编译和烧录。 **验证库文件** 烧录完成后,在设备上检查库文件: ```bash ls -l /usr/lib/libhello* ``` 预期输出: ```plaintext -rw-r--r--. 2 root root 5002 Jan 1 1970 /usr/lib/libhello.a lrwxrwxrwx. 1 root root 15 Jul 25 06:26 /usr/lib/libhello.so -> libhello.so.1.0 lrwxrwxrwx. 1 root root 15 Jul 25 06:26 /usr/lib/libhello.so.1 -> libhello.so.1.0 -rwxr-xr-x. 2 root root 5968 Jan 1 1970 /usr/lib/libhello.so.1.0 ``` **运行测试程序** 静态库测试: ```bash gcc static_test_helloworld.c -lhello -static -o static_hello ./static_hello ``` 预期输出: ```plaintext static lib test [LIB] Hello, world! ``` 动态库测试: ```bash gcc dynamic_test_helloworld.c /usr/lib/libhello.so -o dynamic_hello ./dynamic_hello ``` 预期输出: ```plaintext dynamic lib test [LIB] Hello, world! ``` # 注意事项 1. **层优先级**:确保自定义层的配置正确,避免与其他层冲突 2. **许可证声明**:务必正确设置LICENSE和LIC_FILES_CHKSUM 3. **文件权限**:注意可执行文件和库文件的权限设置 4. **符号链接**:动态库的符号链接必须正确设置 5. **依赖关系**:如果库依赖其他包,需在配方中声明DEPENDS 6. **版本管理**:建议使用版本号管理库文件 # 常见问题 ## Q1: BitBake编译失败? **检查项**: - 配方语法是否正确 - 源文件路径是否正确 - LICENSE文件是否存在 ## Q2: IPK安装失败? **解决方法**: - 确保文件系统已挂载为读写模式 - 检查磁盘空间是否充足 - 查看opkg错误日志 ## Q3: 动态库找不到? **解决方法**: - 检查LD_LIBRARY_PATH环境变量 - 确认符号链接是否正确 - 运行 *ldconfig* 更新库缓存 # 相关文档 - [开发环境搭建](<../开发环境搭建/开发环境搭建.md>) - [镜像构建](<../镜像构建/镜像构建.md>) - [镜像烧录](<../镜像烧录/镜像烧录.md>) - [交叉编译工具链](<../交叉编译工具链/交叉编译工具链.md>) - [内核编译与更新](<../内核编译与更新/内核编译与更新.md>) # 总结 通过本文档的指导,您可以在Yocto环境中: - 创建自定义应用程序和库 - 生成IPK安装包进行单独部署 - 将组件集成到系统镜像中 - 验证和测试自定义组件 掌握这些技能后,您可以根据实际需求扩展和定制系统功能。